package com.hup.joystick.service.joyEvent;

import com.hup.joystick.constant.FunctionConstant.FunctionType;
import com.hup.joystick.model.FunctionConfig;
import com.hup.joystick.model.FunctionConfig.FunctionItem;
import com.hup.joystick.model.joystick.StandardEvent;
import com.hup.joystick.model.joystick.StandardEvent.StandardAction;
import com.hup.joystick.model.joystick.StandardKey;
import lombok.extern.log4j.Log4j2;

import java.awt.*;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * @author hugan
 * @date 2020/10/22
 */
@Log4j2
public class KeyBoardFunctionHandler implements IJoyEventHandler {

    /**
     * 仅{@link FunctionType#KEYBOARD}的功能,且[标准按键][键盘按键]长度至少是1的
     */
    private final ArrayList<FunctionItem> lstPressed = new ArrayList<>();
    private final Robot robot;

    public KeyBoardFunctionHandler(Robot robot) {
        this.robot = robot;
    }

    @Override
    public void releaseAllActiveFunction() {
        for (FunctionItem function : lstPressed) robotRelease(function);
        lstPressed.clear();
    }

    @Override
    public void handleRelease(StandardEvent e, StandardKey standardKey) {
        IJoyEventHandler.matchReleaseBtnFunction(standardKey, lstPressed, this::robotRelease);
    }

    @Override
    public void handlePress(ArrayList<StandardAction> newPress, ArrayList<StandardAction> currentPress,
            FunctionConfig matchConfig) {
        for (Iterator<StandardAction> iterator = newPress.iterator(); iterator.hasNext(); ) {
            StandardAction press = iterator.next();
            //log.debug("press={}", press);

            FunctionItem function = IJoyEventHandler.matchPressBtnFunction(press, currentPress, matchConfig,
                    f -> f.functionType == FunctionType.KEYBOARD && !f.lstStandardKey.isEmpty() && !f.lstKeyCode.isEmpty());
            if (function == null) continue;
            //有符合功能
            iterator.remove();//移除已处理的[新按下事件]
            if (!lstPressed.contains(function)) {
                //一个事件中,同时按下多个键时,会有多个符合的action,所以要过滤,但不能跳过上面的匹配逻辑
                lstPressed.add(function);
                robotPress(function);
            }
        }
    }

    private void robotRelease(FunctionItem function) {
        //log.info("[{}].release", function.getString(null));
        for (Integer keyCode : function.lstKeyCode) robot.keyRelease(keyCode);
    }

    private void robotPress(FunctionItem function) {
        //log.info("[{}].press", function.getString(null));
        for (Integer keyCode : function.lstKeyCode) robot.keyPress(keyCode);
    }

}
